package com.iking.toolkit.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.mock.web.MockMultipartFile;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 功能描述:pdf工具类
 *
 * @author: yfl
 * @date: 2025/8/8 12:18
 */
@Slf4j
public class PdfUtil {

    /**
     * 将PDF转换为图片类PDF
     *
     * @param pdfFile 上传的PDF文件
     * @param dpi     输出图片的分辨率
     * @return 转换后的图片类PDF的MultipartFile
     * @throws IOException 处理过程中发生的IO异常
     */
    public static MultipartFile toImagePdf(MultipartFile pdfFile, Integer dpi) throws IOException {
        // 验证输入文件
        if (pdfFile.isEmpty()) {
            throw new IllegalArgumentException("上传的PDF文件不能为空");
        }

        String originalFilename = pdfFile.getOriginalFilename();
        if (originalFilename == null || !originalFilename.toLowerCase().endsWith(".pdf")) {
            throw new IllegalArgumentException("请上传PDF格式的文件");
        }

        // 确保DPI有效（默认300）
        if (dpi == null || dpi <= 0) {
            dpi = 300;
        }

        // 读取上传的PDF文件
        try (InputStream inputStream = pdfFile.getInputStream();
             PDDocument sourceDoc = PDDocument.load(inputStream)) {

            // 创建新的PDF文档（图片类PDF）
            try (PDDocument targetDoc = new PDDocument()) {
                PDFRenderer renderer = new PDFRenderer(sourceDoc);

                // 遍历PDF的每一页，转换为图片后添加到新PDF
                for (int pageIndex = 0; pageIndex < sourceDoc.getNumberOfPages(); pageIndex++) {
                    // 1. 将PDF页渲染为图片（关键：保留原始尺寸）
                    BufferedImage image = renderer.renderImageWithDPI(pageIndex, dpi);
                    int imageWidth = image.getWidth();  // 图片实际宽度（像素）
                    int imageHeight = image.getHeight();// 图片实际高度（像素）

                    // 2. 关键改进：根据图片尺寸创建匹配的PDF页面
                    // PDF单位是点（1点 = 1/72英寸），转换公式：点 = 像素 * 72 / DPI
                    float pageWidth = imageWidth * 72f / dpi;   // 页面宽度（点）
                    float pageHeight = imageHeight * 72f / dpi; // 页面高度（点）
                    PDRectangle customSize = new PDRectangle(pageWidth, pageHeight);
                    PDPage page = new PDPage(customSize); // 使用自定义尺寸页面
                    targetDoc.addPage(page);

                    // 3. 将图片添加到新页面（无缩放，1:1匹配）
                    try (PDPageContentStream contentStream = new PDPageContentStream(targetDoc, page)) {
                        PDImageXObject pdImage = LosslessFactory.createFromImage(targetDoc, image);

                        // 直接按图片实际尺寸绘制（左上角对齐，无缩放）
                        contentStream.drawImage(pdImage, 0, 0, pageWidth, pageHeight);
                    }
                }

                // 将新PDF文档写入字节数组输出流
                try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
                    targetDoc.save(outputStream);
                    outputStream.flush();

                    // 将字节数组转换为MultipartFile
                    byte[] pdfBytes = outputStream.toByteArray();
                    String fileName = originalFilename.replace(".pdf", ".pdf");

                    return new MockMultipartFile(
                            "file",
                            fileName,
                            "application/pdf",
                            new ByteArrayInputStream(pdfBytes)
                    );
                }
            }
        }
    }
}
